package com.songlanyun.modules.supplychainmessage.service.impl;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.songlanyun.common.enums.RightsOrderConstant;
import com.songlanyun.common.exception.RRException;
import com.songlanyun.common.supplychainapi.logistic.ApiLogisticCommon;
import com.songlanyun.common.supplychainapi.logistic.model.Logistic;
import com.songlanyun.common.supplychainapi.order.ApiOrderCommon;
import com.songlanyun.common.utils.custom.ClassConvertUtils;
import com.songlanyun.modules.goods.entity.Goods;
import com.songlanyun.modules.goods.model.dto.GoodsStatusDTO;
import com.songlanyun.modules.goods.service.GoodsService;
import com.songlanyun.modules.order.entity.ChildOrder;
import com.songlanyun.modules.order.entity.Order;
import com.songlanyun.modules.order.service.ChildOrderService;
import com.songlanyun.modules.order.service.OrderService;
import com.songlanyun.modules.payrefund.entity.PayRefundOrder;
import com.songlanyun.modules.rabbitmq.mq.producer.SendOrderOrRightsOrderMsgService;
import com.songlanyun.modules.rights.entity.RightsOrder;
import com.songlanyun.modules.rights.model.dto.RightsOrderOperateDTO;
import com.songlanyun.modules.rights.service.RightsOrderService;
import com.songlanyun.modules.ship.entity.OrderPackage;
import com.songlanyun.modules.ship.model.dto.ExpressShipDTO;
import com.songlanyun.modules.ship.model.dto.ShipItemDTO;
import com.songlanyun.modules.ship.service.OrderPackageService;
import com.songlanyun.modules.supplychainmessage.enums.MessageCallbackType;
import com.songlanyun.modules.supplychainmessage.model.GoodsAfterSalesCommonResult;
import com.songlanyun.modules.supplychainmessage.model.GoodsFlowCommonResult;
import com.songlanyun.modules.supplychainmessage.model.GoodsOperationCommonResult;
import com.songlanyun.modules.supplychainmessage.model.MessageCommon;
import com.songlanyun.modules.supplychainmessage.service.SupplyChainMessageService;
import com.songlanyun.modules.thirdcallbacklog.entity.ThirdCallBackLogEntity;
import com.songlanyun.modules.thirdcallbacklog.service.ThirdCallBackLogService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.Objects;

/**
 * 消息回调
 *
 * @author lijiahe 2022-02-25
 */
@Slf4j
@Service
public class SupplyChainMessageServiceImpl implements SupplyChainMessageService {


    @Resource
    private RedissonClient redissonClient;
    @Resource
    private ThirdCallBackLogService thirdCallBackLogService;

    @Resource
    private ApiLogisticCommon apiLogisticCommon;

    @Resource
    private OrderPackageService orderPackageService;


    @Resource
    private OrderService orderService;

    @Resource
    private ChildOrderService childOrderService;

    @Resource
    private SendOrderOrRightsOrderMsgService sendOrderOrRightsOrderMsgService;


    @Resource
    private RightsOrderService rightsOrderService;

    @Resource
    private GoodsService goodsService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean callback(Map<String, Object> params) {
        log.info("----------------回调入参：{}", params);

        try {
            MessageCommon<Object> messageCommon = ClassConvertUtils.stringToClassSnake(JSON.toJSONString(params), new TypeReference<MessageCommon<Object>>() {
            });

            String data = JSON.toJSONString(messageCommon.getData());

            MessageCallbackType type = MessageCallbackType.getByCode(messageCommon.getType());
            if (ObjectUtil.isNull(type)) {
                return false;
            }

            //保存第三方回调日志
            ThirdCallBackLogEntity thirdCallBackLogEntity =
                    ThirdCallBackLogEntity.builder()
                            .pushId(messageCommon.getId())
                            .pushTime(new Date(messageCommon.getPushTime()))
                            .type(messageCommon.getType())
                            .desc(type.desc())
                            .data(data)
                            .build();
            thirdCallBackLogService.save(thirdCallBackLogEntity);

            switch (type) {
                case GOODS_ON_SALE:
                    // 商品上架
                    return this.goodsOnSale(data);
                case GOODS_UNDERCARRIAGE:
                    // 商品下架
                    return this.goodsUndercarriage(data);
                case GOODS_ALTER:
                    // 商品修改
                    return this.goodsAlter(data);
                case GOODS_PRICE_ALTER:
                    // 商品价格变更
                    return this.goodsPriceAlter(data);
                case ORDER_SUCCESS:
                    // 交易成功
                    return this.orderSuccess(data);
                case ORDER_DELIVERY:
                    // 商家已发货
                    return this.orderDelivery(data);
                case ORDER_DELIVERED:
                    // 商品已收货
                    return this.orderDelivered(data);
                case AFTER_SALE_SUCCESS:
                    // 售后退款到账
                    return this.afterSaleSuccess(data);
                case AFTER_SALE_AGREE:
                    // 售后同意
                    return this.afterSaleAgree(data);
                case AFTER_SALE_REFUSE:
                    // 售后拒绝
                    return this.afterSaleRefuse(data);
                case GOODS_STORAGE_ADD:
                    // 商品库添加
                    return this.goodsStorageAdd(data);
                case GOODS_STORAGE_REMOVE:
                    // 移除商品库商品
                    return this.goodsStorageRemove(data);
                default:
                    break;
            }
        } catch (Exception e) {
            log.error("----------------回调失败：{}", e.getMessage());
        }
        return false;
    }

    /**
     * 商品上架
     *
     * @param data
     * @return
     */
    private Boolean goodsOnSale(String data) {
        try {
            GoodsOperationCommonResult result =
                    ClassConvertUtils.stringToClass(data, new TypeReference<GoodsOperationCommonResult>() {
                    }, PropertyNamingStrategy.LOWER_CAMEL_CASE);
            Long[] goodsIds = result.getGoodsIds();
            for (int i=0;i<goodsIds.length;i++) {
                Goods goods = goodsService.loadByThirdSpuId(goodsIds[i]);
                if(ObjectUtil.isNotNull(goods))
                {
                    GoodsStatusDTO dto = new GoodsStatusDTO();
                    dto.setGoodsId(goods.getId());
                    dto.setVerifyStatus(1);
                    dto.setAdded(true);
                    goodsService.added(goods.getShopId(),dto);
                }
            }
            return true;
        } catch (Exception e) {
            throw new RRException("回调第三方商品上架消息出错" + e.getMessage());
        }
    }

    /**
     * 商品下架
     *
     * @param data
     * @return
     */
    private Boolean goodsUndercarriage(String data) {
        try {
            GoodsOperationCommonResult result = ClassConvertUtils.stringToClass(data, new TypeReference<GoodsOperationCommonResult>() {
            },PropertyNamingStrategy.LOWER_CAMEL_CASE);
            Long[] goodsIds = result.getGoodsIds();
            for (int i=0;i<goodsIds.length;i++) {
                Goods goods = goodsService.loadByThirdSpuId(goodsIds[i]);
                if(ObjectUtil.isNotNull(goods))
                {
                    GoodsStatusDTO dto = new GoodsStatusDTO();
                    dto.setGoodsId(goods.getId());
                    dto.setVerifyStatus(2);
                    dto.setAdded(false);
                    goodsService.added(goods.getShopId(),dto);
                }
            }
            return true;
        } catch (Exception e) {
            throw new RRException("回调第三方商品下架出错" + e.getMessage());
        }
    }

    /**
     * 商品修改
     *
     * @param data
     * @return
     */
    private Boolean goodsAlter(String data) {
        try {
            GoodsOperationCommonResult result =
                    ClassConvertUtils.stringToClass(data, new TypeReference<GoodsOperationCommonResult>() {
                    },PropertyNamingStrategy.LOWER_CAMEL_CASE);

            return true;
        } catch (Exception e) {
            throw new RRException("回调第三方商品修改出错" + e.getMessage());
        }
    }

    /**
     * 商品价格变更
     *
     * @param data
     * @return
     */
    private Boolean goodsPriceAlter(String data) {
        try {
            GoodsOperationCommonResult result =
                    ClassConvertUtils.stringToClass(data, new TypeReference<GoodsOperationCommonResult>() {
                    },PropertyNamingStrategy.LOWER_CAMEL_CASE);

            return true;
        } catch (Exception e) {
            throw new RRException("回调第三方商品价格变更出错" + e.getMessage());
        }
    }

    /**
     * 交易成功
     *
     * @param data
     * @return
     */
    private Boolean orderSuccess(String data) {
        try {
            GoodsFlowCommonResult result =
                    ClassConvertUtils.stringToClass(data, new TypeReference<GoodsFlowCommonResult>() {
                    },PropertyNamingStrategy.LOWER_CAMEL_CASE);

            return true;
        } catch (Exception e) {
            throw new RRException("回调第三方交易成功消息出错" + e.getMessage());
        }
    }

    /**
     * 商品已收货
     *
     * @param data
     * @return
     */
    private Boolean orderDelivered(String data) {
        try {
            GoodsFlowCommonResult result =
                    ClassConvertUtils.stringToClass(data, new TypeReference<GoodsFlowCommonResult>() {
                    },PropertyNamingStrategy.LOWER_CAMEL_CASE);

            return true;
        } catch (Exception e) {
            throw new RRException("回调第三方商品已收货出错" + e.getMessage());
        }
    }

    /**
     * 商家已发货
     *
     * @param data
     * @return
     */
    private Boolean orderDelivery(String data) {
        try {
            GoodsFlowCommonResult result =
                    ClassConvertUtils.stringToClass(data, new TypeReference<GoodsFlowCommonResult>() {
                    },PropertyNamingStrategy.LOWER_CAMEL_CASE);
            Map<String, Object> params = new HashMap<>();
            params.put("orderSn",result.getOrderSn());
            params.put("sku",result.getSku());
            Logistic logistic = apiLogisticCommon.logistic(params);
            if(ObjectUtil.isNotNull(logistic))
            {
                try {
                    Order order = orderService.loadByOrderNo(result.getOrderSn(), false);
                    ChildOrder childOrder = childOrderService.loadByOrderAndThirdSkuId(order.getId(), result.getSku(), false);
                    if (ObjectUtil.isNotNull(order) && ObjectUtil.isNotNull(childOrder)) {
                        ExpressShipDTO dto = new ExpressShipDTO();
                        dto.setOrderId(order.getId());
                        dto.setLogisticCode(logistic.getInfo().getNo());
                        dto.setExpressName(logistic.getInfo().getName());
                        dto.setExpressCode(logistic.getInfo().getName());
                        ShipItemDTO shipItemDTO = new ShipItemDTO();
                        shipItemDTO.setOrderId(order.getId());
                        shipItemDTO.setChildOrderId(childOrder.getId());
                        shipItemDTO.setShipNum(childOrder.getNumber());
                        List<ShipItemDTO> shipItemDTOList = new ArrayList<>();
                        shipItemDTOList.add(shipItemDTO);
                        dto.setShipItems(shipItemDTOList);
                        dto.setThirdShip(true);


                        OrderPackage orderPackage = orderPackageService.partExpressShip(order.getShopId(), dto);
                        sendOrderOrRightsOrderMsgService.expressShipSuccessSendMsg(orderPackage);
                    }
                }
                catch (Exception ex)
                {
                    log.info("第三方商品消息通知发货后，本系统发货错误:"+ex.getMessage());
                }
            }
            return true;
        } catch (Exception e) {
            throw new RRException("回调第三方商家已发货出错" + e.getMessage());
        }
    }

    /**
     * 售后退款到账
     *
     * @param data
     * @return
     */
    private Boolean afterSaleSuccess(String data) {
        try {
            GoodsAfterSalesCommonResult result =
                    ClassConvertUtils.stringToClass(data, new TypeReference<GoodsAfterSalesCommonResult>() {
                    },PropertyNamingStrategy.LOWER_CAMEL_CASE);

            PayRefundOrder payRefundOrder = rightsOrderService.thirdRefund(result.getAfterSaleId());
            if (payRefundOrder != null && RightsOrderConstant.RightsRefundStatus.SUCCESS.equals(payRefundOrder.getRightsRefundStatus())) {
                sendOrderOrRightsOrderMsgService.rightsRefundSuccessSendMsg(payRefundOrder);
            }
            return true;
        } catch (Exception e) {
            throw new RRException("回调第三方售后退款到账出错" + e.getMessage());
        }
    }

    /**
     * 售后同意
     *
     * @param data
     * @return
     */
    private Boolean afterSaleAgree(String data) {
        try {
            GoodsAfterSalesCommonResult result =
                    ClassConvertUtils.stringToClass(data, new TypeReference<GoodsAfterSalesCommonResult>() {
                    },PropertyNamingStrategy.LOWER_CAMEL_CASE);
            Long afterSaleId = result.getAfterSaleId();
            RightsOrder rightsOrder = rightsOrderService.loadByThirdRightsId(afterSaleId);
            if(ObjectUtil.isNotNull(rightsOrder)) {
                RightsOrderOperateDTO dto = new RightsOrderOperateDTO();
                dto.setRightsOrderId(rightsOrder.getId());
                rightsOrder = rightsOrderService.agree(rightsOrder.getShopId(), dto);
                sendOrderOrRightsOrderMsgService.rightsAgreeSendMsg(rightsOrder);
            }

            return true;
        } catch (Exception e) {
            throw new RRException("回调第三方售后同意出错" + e.getMessage());
        }
    }

    /**
     * 售后拒绝
     *
     * @param data
     * @return
     */
    private Boolean afterSaleRefuse(String data) {
        try {
            GoodsAfterSalesCommonResult result =
                    ClassConvertUtils.stringToClass(data, new TypeReference<GoodsAfterSalesCommonResult>() {
                    },PropertyNamingStrategy.LOWER_CAMEL_CASE);

            Long afterSaleId = result.getAfterSaleId();
            RightsOrder rightsOrder = rightsOrderService.loadByThirdRightsId(afterSaleId);
            if( ObjectUtil.isNotNull(rightsOrder)) {
                RightsOrderOperateDTO dto = new RightsOrderOperateDTO();
                dto.setRightsOrderId(rightsOrder.getId());
                rightsOrder = rightsOrderService.refuse(rightsOrder.getShopId(), dto);
                sendOrderOrRightsOrderMsgService.rightsRefuseSendMsg(rightsOrder);
            }
            return true;
        } catch (Exception e) {
            throw new RRException("回调第三方售后拒绝出错" + e.getMessage());
        }
    }

    /**
     * 商品库添加
     *
     * @param data
     * @return
     */
    private Boolean goodsStorageAdd(String data) {
        try {
            GoodsOperationCommonResult result =
                    ClassConvertUtils.stringToClass(data, new TypeReference<GoodsOperationCommonResult>() {
                    },PropertyNamingStrategy.LOWER_CAMEL_CASE);

            return true;
        } catch (Exception e) {
            throw new RRException("回调第三方商品库添加出错" + e.getMessage());
        }
    }

    /**
     * 移除商品库商品
     *
     * @param data
     * @return
     */
    private Boolean goodsStorageRemove(String data) {
        try {
            GoodsOperationCommonResult result =
                    ClassConvertUtils.stringToClass(data, new TypeReference<GoodsOperationCommonResult>() {
                    },PropertyNamingStrategy.LOWER_CAMEL_CASE);

            return true;
        } catch (Exception e) {
            throw new RRException("回调第三方移除商品库商品出错" + e.getMessage());
        }
    }
}
